package pres.liko.blackapi.service.impl;

import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.data.r2dbc.core.R2dbcEntityTemplate;
import org.springframework.data.relational.core.query.Criteria;
import org.springframework.data.relational.core.query.Query;
import org.springframework.data.relational.core.query.Update;
import org.springframework.stereotype.Service;
import pres.liko.blackapi.event.BlackApiChangeEvent;
import pres.liko.blackapi.pojo.Dc3BlackApi;
import pres.liko.blackapi.service.BlackApiService;
import pres.liko.iot.bean.R;
import pres.liko.iot.utils.SnowFlakeUtil;
import reactor.core.publisher.Mono;

import java.time.LocalDateTime;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * @ClassName: BlackApiServiceImpl
 * @Auther: liko
 * @Description:
 * @Date: 2022/11/2 21:48
 */
@Service
public class BlackApiServiceImpl implements BlackApiService {

    private R2dbcEntityTemplate r2dbcEntityTemplate;
    private ApplicationContext context;

    @Autowired
    public BlackApiServiceImpl(R2dbcEntityTemplate r2dbcEntityTemplate, ApplicationContext context) {
        this.r2dbcEntityTemplate = r2dbcEntityTemplate;
        this.context = context;
    }

    @Override
    public Mono<R<Object>> addApi(Mono<Dc3BlackApi> blackApiMono) {
        return blackApiMono.filter(
                dc3BlackApi -> StringUtils.isNotBlank(dc3BlackApi.getUrl())
        ).doOnNext(dc3BlackApi -> {
            dc3BlackApi.setId(SnowFlakeUtil.getSnowFlakeId().toString());
            dc3BlackApi.setCreateTime(LocalDateTime.now());
            dc3BlackApi.setUpdateTime(LocalDateTime.now());
        }).flatMap(dc3BlackApi -> {
            return r2dbcEntityTemplate.select(Dc3BlackApi.class)
                    .from("dc3_black_api")
                    .matching(Query.query(Criteria.where("url").is(dc3BlackApi.getUrl())))
                    .all()
                    .count()
                    .filter(aLong -> aLong == 0)
                    .flatMap(dc3BlackApi1 -> {
                        return r2dbcEntityTemplate.insert(dc3BlackApi)
                                .map(blackApi -> {
                                    // 发送消息通知 BlackIpChangeEvent
                                    context.publishEvent(new BlackApiChangeEvent());
                                    return R.ok();
                                }).defaultIfEmpty(R.fail("添加失败"));
                    })
                    .defaultIfEmpty(R.fail("url已添加"));
        }).defaultIfEmpty(R.fail("url不能为空"));
    }

    @Override
    public Mono<R<Set<String>>> findAllEnable() {
        return r2dbcEntityTemplate.select(
                Query.query(
                        Criteria.where("deleted").is(0)
                ).columns("url"), Dc3BlackApi.class)
                .map(Dc3BlackApi::getUrl)
                .collect(Collectors.toSet())
                .map(dc3BlackApi -> R.ok(dc3BlackApi));
    }

    @Override
    public Mono<R<Object>> updateEnableById(String id, String deleted) {
        return r2dbcEntityTemplate.select(Dc3BlackApi.class)
                .matching(Query.query(Criteria.where("id").is(id)))
                .first()
                .flatMap(dc3BlackApi -> {
                    return r2dbcEntityTemplate.update(Dc3BlackApi.class)
                            .inTable("dc3_black_api")
                            .matching(Query.query(Criteria.where("id").is(id)))
                            .apply(Update.update("deleted", deleted))
                            .filter(integer -> integer > 0)
                            .map(blackApi -> {
                                // 发送消息通知 BlackIpChangeEvent
                                context.publishEvent(new BlackApiChangeEvent());
                                return R.ok();
                            }).defaultIfEmpty(R.fail("删除失败"));
                }).defaultIfEmpty(R.fail("id不存在"));
    }

    @Override
    public Mono<R<Object>> deleteById(String id) {
        return r2dbcEntityTemplate.select(Dc3BlackApi.class)
                .matching(Query.query(Criteria.where("id").is(id)))
                .first()
                .flatMap(dc3BlackApi -> {
                    return r2dbcEntityTemplate.delete(Dc3BlackApi.class)
                            .from("dc3_black_api")
                            .matching(Query.query(Criteria.where("id").is(id)))
                            .all()
                            .filter(integer -> integer > 0)
                            .map(blackApi -> {
                                // 发送消息通知 BlackIpChangeEvent
                                context.publishEvent(new BlackApiChangeEvent());
                                return R.ok();
                            })
                            .defaultIfEmpty(R.fail("删除失败"));
                }).defaultIfEmpty(R.fail("id不存在"));
    }


}
